#include "Circle2DHandler.h"
#include "CmdManager.h"
#include "SendPointHandlerBase.h"
#include "Scene.h"
#include "Ucs.h"
#include "qundostack.h"
#include "Operation/OpAdd.h"
#include "geometricutility.h"
#include "DblPoint.h"
#include "QtOSGWidget.h"
#include "SelectHandler3D.h"

Circle2DHandler::Circle2DHandler()
{
}

Circle2DHandler::~Circle2DHandler()
{
}

void Circle2DHandler::input(const QVariant& data, const QString& rawInput, CommandSource cs)
{
	auto widget3D = getWidget();
	auto sph = getSendPointHandler();
	auto scene = getScene();
	auto ucs = scene->getCurrentUCS();
	auto selector = qobject_cast<SelectHandler3D*>(getSelectHandler());
	if (data.type() == QVariant::Bool && !data.toBool())
	{
		if (m_cir)
		{
			widget3D->pauseRenderThread();
			ucs->removeChild(m_cir);
			widget3D->resumeRenderThread();
		}
		emit finished();
		return;
	}

	if (status() == 0)
	{
		if (sph)
		{
			sph->setPointMask(CS_LBTNDOWN);
		}
		m_cir = std::make_shared<Arc2D>(ucs.get());
		m_cir->setColor(ucs->getUCSColor());
		widget3D->pauseRenderThread();
		ucs->addChild(m_cir);
		widget3D->resumeRenderThread();
		cmdManager()->setPlane((Plane2DKind)ucs->getKind());
		prompt(1, tr("指定圆的中心或[3点(3P)/2点(2P)]: "));
		return;
	}

	if (status() == 1)
	{
		if (sph)
		{
			sph->setPointMask(CS_LBTNDOWN | CS_MOUSEMOVE);
		}
		osg::Vec3d ucspt;
		if (data.type() == QVariant::String)
		{
			auto command = data.value<QString>();
			if (command == tr("3P") || command == tr("3p"))
			{
				prompt(2, tr("指定圆上的第一点: "));
			}
			else if (command == tr("2P") || command == tr("2p"))
			{
				prompt(4,tr("指定圆的直径的第一点: "));
			}
			else
			{
				remark(tr("无效的输入"));
			}
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			m_centerPt = ucspt;
			showRubberLine(true);
			if (cs != CS_MOUSEMOVE)
			{
				setRubberLineP1(ucspt);
				prompt(5, tr("指定圆的半径: "));
			}	
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 2)
	{
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			m_startPt = ucspt;
			showRubberLine(true);
			if (cs!= CS_MOUSEMOVE)
			{
				setRubberLineP1(m_startPt);
				prompt(3, tr("指定圆的第二点: "));
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 3)
	{
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			m_secondPt = ucspt;	
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				if (m_secondPt != m_startPt)
				{
					showRubberLine(false);
					prompt(6, tr("指定圆的第三点: "));
				}
				else
				{
					remark(tr("无效的输入"));
				}
			}
		}
		else
		{
				remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 4)
	{
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			m_startPt = ucspt;
			showRubberLine(true);
			if (cs != CS_MOUSEMOVE)
			{
				setRubberLineP1(ucspt);
				prompt(7, tr("指定圆的直径的第二点: "));
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}
	
	if (status() == 5)
	{
		osg::Vec3d ucspt;
		if (data.type() == QVariant::Double)
		{
			double radius = data.value<double>();
			if (radius <= 0.0)
			{
				remark(tr("圆的半径必须不小于0"));
			}
			m_cir->set(m_centerPt, radius, 0, 2 * M_PI);
			drawFinished(scene);
			emit finished();
		}
		else if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			auto radius = (m_centerPt - ucspt).length();
			if (radius < 0.0)
			{
				remark(tr("无效的输入"));
				return;
			}
			m_cir->setCircle(m_centerPt, radius);
			if (cs == CS_MOUSEMOVE)
			{
				setRubberLineP2(ucspt);
			}
			else
			{
				drawFinished(scene);
				emit finished();
				return;
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 6)
	{
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			m_endPt = ucspt;
			CDblPoint center;
			double radius;
			bool success = CalCircleFrom3P({ m_startPt.x(),m_startPt.y() }, { m_secondPt.x(),m_secondPt.y() }, {m_endPt.x(),m_endPt.y()}, center, radius);
			if (success)
			{
				m_cir->setCircle(osg::Vec3d(center.x, center.y, 0), radius);
				if (cs != CS_MOUSEMOVE)
				{
					drawFinished(scene);
					emit finished();
				}
			}
			else
			{
				if (cs != CS_MOUSEMOVE)
					remark(tr("无效的输入"));
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}

	if (status() == 7)
	{
		osg::Vec3d ucspt;
		if (getPoint2D(*ucs, data, rawInput, cs, ucspt))
		{
			m_endPt = ucspt;
			setRubberLineP2(ucspt);
			double dx = m_startPt.x() - m_endPt.x();
			double dy = m_startPt.y() - m_endPt.y();
			bool bSuccess = dx != 0.0 || dy != 0.0;
			if (bSuccess)
			{
				dx /= 2.0;
				dy /= 2.0;
				double radius = sqrt(dx*dx + dy * dy);
				m_cir->setCircle(osg::Vec3d((m_startPt.x() + m_endPt.x()) / 2.0, (m_startPt.y() + m_endPt.y()) / 2.0, 0), radius);
			}
			if (cs != CS_MOUSEMOVE)
			{
				if (bSuccess)
				{
					drawFinished(scene);
					emit finished();
				}
				else
				{
					remark(tr("无效的输入"));
				}
			}
		}
		else
		{
			remark(tr("无效的输入"));
		}
		return;
	}
}

void Circle2DHandler::drawFinished(Scene * scene)
{
	auto undoStack = scene->undoStack();
	std::set<std::shared_ptr<INode>> children;
	children.insert(m_cir);
	undoStack->push(new OpAdd(children));
}



